import { HttpException, HttpStatus, Injectable, Logger } from '@nestjs/common'
import { InjectRepository } from '@nestjs/typeorm'
import { catchError, map } from 'rxjs/operators'
import { Repository } from 'typeorm'
import { CreateArticleDto } from './dto/create-article.dto'
import { UpdateArticleDto } from './dto/update-article.dto'
import { ArticleEntity } from './entities/article.entity'
import { HttpService } from '@nestjs/axios'
import { getRepoInfo } from '@/shared/utils'
import { lastValueFrom } from 'rxjs'

@Injectable()
export class ArticleService {
  constructor(
    @InjectRepository(ArticleEntity)
    private readonly articleRepository: Repository<ArticleEntity>,
    private httpService: HttpService,
  ) {}

  // 新增
  async create(dto: CreateArticleDto) {
    const result = await this.articleRepository.create(dto)
    await this.articleRepository.save(result)

    return result
  }

  // 列表
  async findAll(queryParams) {
    const { page, limit, title, version, tagId, navId, appId, backendId } = queryParams
    const sql = this.articleRepository.createQueryBuilder('article').leftJoinAndSelect('article.backend', 'backend').leftJoinAndSelect('article.tags', 'tags').leftJoinAndSelect('article.category', 'category').orderBy('article.id', 'DESC')

    appId && sql.where('article.appId = :appId', { appId })
    navId && sql.andWhere('article.navId = :navId', { navId })
    version && sql.andWhere('article.version = :version', { version })
    backendId && sql.andWhere('backend.id = :backendId', { backendId: +backendId })
    tagId && sql.andWhere('tags.id = :tagId', { tagId: +tagId })
    title && sql.andWhere('article.title like :title', { title: `%${title}%` })

    sql.skip((page - 1) * limit).take(limit)

    const result = await sql.getManyAndCount()

    return result
  }

  // 详情
  async findOne(id) {
    const result: any = await this.articleRepository.findOne({ where: { id }, relations: ['backend', 'tags'] })
    const source = result.github ? 'github' : 'gitee'
    const host = `${source}.com`

    const { username, repoName } = getRepoInfo(result[source], host)
    const readme = await lastValueFrom(await this.getReadme(username, repoName, host))

    const md = Buffer.from(readme.content, 'base64').toString('utf-8')
    result.md = md

    await this.articleRepository.update(id, { viewsCount: result.viewsCount + 1 })

    return result
  }

  // 获取readme
  async getReadme(username: string, repoName: string, source?: string) {
    let apiUrl = ''

    if (source === 'github.com') {
      apiUrl = `https://api.github.com/repos/${username}/${repoName}/readme`
    } else if (source === 'gitee.com') {
      apiUrl = `https://gitee.com/api/v5/repos/${username}/${repoName}/readme`
    } else {
      throw new HttpException('不支持的来源', 400)
    }

    return this.httpService.get(apiUrl).pipe(
      map((response) => {
        return response.data
      }),
      catchError((e) => {
        throw new HttpException('出错了', e.response.status)
      }),
    )
  }

  // 修改
  async update(id, dto: UpdateArticleDto) {
    const old = await this.articleRepository.findOne({ where: { id } })
    const vo = await this.articleRepository.merge(old, dto)

    return this.articleRepository.save(vo)
  }

  // 删除
  async remove(id: string) {
    const result = await this.articleRepository.delete(id)
    Logger.log(`删除返回数据：${JSON.stringify(result)}`)

    return result.affected || new HttpException('无法删除，请稍候在试', HttpStatus.BAD_REQUEST)
  }
}
